home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Turnbull China Bikeride
/
Turnbull China Bikeride - Disc 2.iso
/
STUTTGART
/
LANG
/
ICON
/
ICONV8
/
Source
/
Common
/
C
/
Popen
< prev
next >
Wrap
Text File
|
1990-09-18
|
7KB
|
409 lines
/* C.Popen: Simulation of pipes */
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "kernel.h"
extern char *mktemp (const char *);
static char *strdup (const char *);
static int os_cmd (char *);
static int cmp_cmd (char *, char *);
#define MAX_PIPE 20
typedef enum
{
unopened = 0,
reading,
writing
}
pipemode;
static struct pipe
{
char *command; /* The command being executed */
char *name; /* The name of the pipe file */
FILE *fd; /* The file used as a pipe */
pipemode pmode; /* The open mode of the pipe */
int retval; /* The return value of the command */
}
pipes[MAX_PIPE];
FILE *popen (char *command, char *mode)
{
FILE *current;
char *name;
int i;
pipemode curmode;
int rval = -1;
char tmp[11];
/* decide on mode */
if ( mode[1] != 0 )
return NULL;
else if ( *mode == 'r' )
curmode = reading;
else if ( *mode == 'w' )
curmode = writing;
else
return NULL;
/* Get a slot in the pipes structure */
for ( i = 0; i < MAX_PIPE; ++i )
{
if ( pipes[i].pmode == unopened )
break;
}
if ( i >= MAX_PIPE )
return NULL;
/* Get a file name to use */
sprintf(tmp, "Pipe%.2d", i);
name = mktemp(tmp);
if ( name == NULL )
return NULL;
/*
* If we're reading, just call system() to get a file filled
* with output.
*/
if ( curmode == reading )
{
char *tmpname;
int oscmd = os_cmd(command);
char cmd[256];
int n;
if (*command == '%')
{
oscmd = 1;
++command;
}
if (!oscmd)
{
char *s;
while (*command && isspace(*command))
++command;
s = command;
while (*s && !isspace(*s))
++s;
n = sprintf(cmd, "%.*s > %s%s",
s - command, command, name, s);
}
else
{
tmpname = mktemp("PipeTmp");
if (tmpname == NULL)
{
free(name);
return NULL;
}
n = sprintf(cmd, "%s{ > %s }", command, tmpname);
}
/* Emergency! Overflow in command buffer! */
if (n > 255)
{
if (oscmd)
{
remove(tmpname);
free(tmpname);
}
free(name);
return NULL;
}
_kernel_setenv("Sys$ReturnCode", "0");
rval = system(cmd);
if (rval == _kernel_ERROR)
{
remove(tmpname);
free(tmpname);
free(name);
return NULL;
}
if (oscmd)
{
int ch;
FILE *in = fopen(tmpname, "r");
FILE *out = fopen(name, "w");
if (in == NULL || out == NULL)
{
remove(tmpname);
free(tmpname);
free(name);
return NULL;
}
/* Strip out CRs from the output */
while ((ch = getc(in)) != EOF && !ferror(out))
{
if (ch != '\r')
putc(ch, out);
}
/* Did we succeed? */
ch = (ferror(in) || ferror(out));
/* Tidy up */
fclose(in);
fclose(out);
remove(tmpname);
free(tmpname);
if (ch)
{
free(name);
return NULL;
}
}
if ( (current = fopen(name,"r")) == NULL )
{
free(name);
return NULL;
}
}
else
{
if ( (current = fopen(name,"w")) == NULL )
{
free(name);
return NULL;
}
}
pipes[i].command = strdup(command);
pipes[i].name = name;
pipes[i].fd = current;
pipes[i].pmode = curmode;
pipes[i].retval = rval;
return current;
}
int pclose (FILE *current)
{
int rval;
int i;
/* Get the appropriate slot in thbe pipes structure */
for ( i = 0; i < MAX_PIPE; ++i )
{
if ( pipes[i].fd == current )
break;
}
if ( i >= MAX_PIPE )
return -1;
if ( pipes[i].pmode == reading )
{
/* Input pipes are just files we're done with */
rval = pipes[i].retval;
fclose(current);
remove(pipes[i].name);
}
else
{
/*
* Output pipes are temporary files we have
* to cram down the throats of programs.
*/
char *command = pipes[i].command;
int oscmd = os_cmd(command);
int n;
char cmd[256];
if (*command == '%')
{
oscmd = 1;
++command;
}
/* Close the pipe file */
fclose(current);
/* Create the required command string */
if (oscmd)
n = sprintf(cmd, "%s{ < %s }", command, pipes[i].name);
else
{
char *s;
while (*command && isspace(*command))
++command;
s = command;
while (*s && !isspace(*s))
++s;
n = sprintf(cmd, "%.*s < %s%s",
s - command, command, pipes[i].name, s);
}
/* Check for overflow in command buffer */
if (n > 255)
rval = -1;
else
{
_kernel_setenv("Sys$ReturnCode", "0");
rval = system(cmd);
}
remove(pipes[i].name);
}
/* clean up current pipe */
pipes[i].pmode = unopened;
free(pipes[i].name);
free(pipes[i].command);
return rval;
}
/* save a string on the heap; return pointer to it */
static char *strdup (const char *str)
{
char *p = malloc(strlen(str)+1);
if (p == NULL)
{
fprintf(stderr,"Not enough memory to save string\n");
exit(1);
}
return (strcpy(p,str));
}
/* Check whether a command is an OS command (binary search on the table
* os_commands of valid OS commands).
*/
static char *os_commands[] =
{
"access", "adfs", "alphabet", "alphabets",
"append", "audio", "basic", "breakclr",
"breaklist", "breakset", "build", "cat",
"cdir", "channelvoice", "close", "configure",
"continue", "copy", "count", "countries",
"country", "create", "debug", "delete",
"deskfs", "dir", "dump", "echo",
"enumdir", "error", "eval", "ex",
"exec", "fileinfo", "fontcat", "fontlist",
"fx", "go", "gos", "help",
"iconsprites", "if", "ignore", "info",
"initstore", "key", "keyboard", "lcat",
"lex", "lib", "list", "load",
"memory", "memorya", "memoryi", "modules",
"obey", "opt", "poduleload", "podules",
"podulesave", "pointer", "print", "qsound",
"quit", "ram", "remove", "rename",
"rmclear", "rmensure", "rmfaster", "rmkill",
"rmload", "rmreinit", "rmrun", "rmtidy",
"rommodules", "run", "save", "schoose",
"scopy", "screenload", "screensave", "sdelete",
"set", "seteval", "setmacro", "settype",
"sflipx", "sflipy", "sget", "shadow",
"shellcli", "show", "showregs", "shut",
"shutdown", "sinfo", "slist", "sload",
"smerge", "snew", "sound", "speaker",
"spool", "spoolon", "srename", "ssave",
"stamp", "status", "stereo", "tempo",
"time", "tuning", "tv", "type",
"unplug", "unset", "up", "voices",
"volume", "wimppalette", "wimpslot", "wimptask",
"wipe"
};
#define NUM_CMDS (sizeof(os_commands) / sizeof(char *))
static int os_cmd (char *cmd)
{
int low = 0;
int high = NUM_CMDS - 1;
while (low <= high)
{
int mid = (high + low) / 2;
int i = cmp_cmd(cmd,os_commands[mid]);
if (i == 0)
return 1;
else if (i < 0)
high = mid - 1;
else
low = mid + 1;
}
return 0;
}
static int cmp_cmd (char *cmd, char *name)
{
while (*name && tolower(*cmd) == *name)
++name, ++cmd;
if (*name)
return (tolower(*cmd) - *name);
return (*cmd != '\0' && !isspace(*cmd));
}
#ifdef test
int main (int argc, char *argv[])
{
FILE *fp;
char *cmd;
if (argc <= 1)
{
printf("Usage Popen [cmd or Popen ]cmd\n");
return 0;
}
cmd = argv[1];
if (*cmd++ == ']')
{
fp = popen(cmd,"w");
fprintf(fp,"hello\nworld\nhow\nare\nyou\n");
pclose(fp);
}
else
{
char buf[500];
fp = popen(cmd,"r");
while (!feof(fp))
{
if (!fgets(buf,499,fp))
{
printf("Read error!\n");
return 1;
}
buf[strlen(buf)-1] = 0;
printf(">%s<\n", buf);
}
pclose(fp);
}
return 0;
}
#endif